<?php

namespace LowCode;

use BadMethodCallException;
use LowCode\Support\Fluent;

/**
 * @method Settings setAppName(string $value)
 * @method Settings setAppAccessMode(string $value = 'backend')
 * @method Settings setAppAuthPageLayout(string $value = 'panel-right'|'panel-center'|'panel-right')
 * @method Settings setAppCheckUpdatesInterval(int $value = 1)
 * @method Settings setAppColorGrayMode(bool $value = true)
 * @method Settings setAppColorWeakMode(bool $value = true)
 * @method Settings setAppCompact(bool $value = true)
 * @method Settings setAppContentCompact(string $value = "wide")
 * @method Settings setAppDefaultAvatar(string $value)
 * @method Settings setAppDynamicTitle(bool $value = true)
 * @method Settings setAppEnableCheckUpdates(bool $value = true)
 * @method Settings setAppEnablePreferences(bool $value = true)
 * @method Settings setAppEnableRefreshToken(bool $value = true)
 * @method Settings setAppLayout(string $value = "sidebar-mixed-nav")
 * @method Settings setAppLocale(string $value = "zh-CN")
 * @method Settings setAppLoginExpiredMode(string $value = "page")
 * @method Settings setAppPreferencesButtonPosition(string $value = "auto")
 * @method Settings setAppWatermark(bool $value = true)
 * @method Settings setBreadcrumbEnable(bool $value = false)
 * @method Settings setBreadcrumbHideOnlyOne(bool $value = false): static
 * @method Settings setBreadcrumbShowHome(bool $value = false)
 * @method Settings setBreadcrumbShowIcon(bool $value = false)
 * @method Settings setBreadcrumbStyleType(string $value = 'background')
 * @method Settings setCopyrightName(string $value)
 * @method Settings setCopyrightLink(string $value)
 * @method Settings setCopyrightDate(string $value)
 * @method Settings setCopyrightEnable(bool $value = true)
 * @method Settings setCopyrightIcp(string $value)
 * @method Settings setCopyrightIcpLink(string $value)
 * @method Settings setCopyrightSettingShow(bool $value = true)
 * @method Settings setFooterEnable(bool $value = true)
 * @method Settings setFooterFixed(bool $value = true)
 * @method Settings setHeaderEnable(bool $value = true)
 * @method Settings setHeaderHidden(bool $value = true)
 * @method Settings setHeaderMenuAlign(string $value = 'start')
 * @method Settings setHeaderMode(string $value = 'fixed')
 * @method Settings setLogoEnable(bool $value = true)
 * @method Settings setLogoSource(string $value = "")
 * @method Settings setNavigationName(bool $value = true)
 * @method Settings setNavigationSplit(bool $value = true)
 * @method Settings setNavigationStyleType(string $value = 'rounded')
 * @method Settings setShortcutKeysEnable(bool $value = true)
 * @method Settings setShortcutKeysGlobalLockScreen(bool $value = true)
 * @method Settings setShortcutKeysGlobalLogout(bool $value = true)
 * @method Settings setShortcutKeysGlobalPreferences(bool $value = true)
 * @method Settings setShortcutKeysGlobalSearch(bool $value = true)
 * @method Settings setSidebarAutoActivateChild(bool $value = true)
 * @method Settings setSidebarCollapsed(bool $value = true)
 * @method Settings setSidebarCollapsedShowTitle(bool $value = true)
 * @method Settings setSidebarEnable(bool $value = true)
 * @method Settings setSidebarExpandOnHover(bool $value = true)
 * @method Settings setSidebarExtraCollapse(bool $value = true)
 * @method Settings setSidebarHidden(bool $value = true)
 * @method Settings setSidebarWidth(int $value = 200)
 * @method Settings setTabbarDraggable(bool $value = true)
 * @method Settings setTabbarEnable(bool $value = true)
 * @method Settings setTabbarHeight(int $value = 38)
 * @method Settings setTabbarKeepAlive(bool $value = true)
 * @method Settings setTabbarMaxCount(int $value = 0)
 * @method Settings setTabbarMiddleClickToClose(bool $value = true)
 * @method Settings setTabbarPersist(bool $value = true)
 * @method Settings setTabbarShowIcon(bool $value = true)
 * @method Settings setTabbarShowMaximize(bool $value = true)
 * @method Settings setTabbarShowMore(bool $value = true)
 * @method Settings setTabbarStyleType(string $value = 'chrome')
 * @method Settings setTabbarWheelable(bool $value = true)
 * @method Settings setThemeBuiltinType(string $value = 'violet')
 * @method Settings setThemeColorDestructive(string $value = 'hsl(348 100% 61%)')
 * @method Settings setThemeColorPrimary(string $value = 'hsl(245 82% 67%)')
 * @method Settings setThemeColorSuccess(string $value = 'hsl(144 57% 58%)')
 * @method Settings setThemeColorWarning(string $value = 'hsl(42 84% 61%)')
 * @method Settings setThemeMode(string $value = 'light')
 * @method Settings setThemeRadius(string $value = '0.25')
 * @method Settings setThemeSemiDarkHeader(bool $value = true)
 * @method Settings setThemeSemiDarkSidebar(bool $value = true)
 * @method Settings setTransitionName(string $value = 'fade-slide')
 * @method Settings setTransitionEnable(bool $value = true)
 * @method Settings setTransitionLoading(bool $value = true)
 * @method Settings setTransitionProgress(bool $value = true)
 * @method Settings setWidgetFullscreen(bool $value = true)
 * @method Settings setWidgetGlobalSearch(bool $value = true)
 * @method Settings setWidgetLanguageToggle(bool $value = true)
 * @method Settings setWidgetLockScreen(bool $value = true)
 * @method Settings setWidgetNotification(bool $value = true)
 * @method Settings setWidgetRefresh(bool $value = true)
 * @method Settings setWidgetSidebarToggle(bool $value = true)
 * @method Settings setWidgetThemeToggle(bool $value = true)
 * @method static Settings appName(string $value)
 * @method static Settings appAccessMode(string $value = 'backend')
 * @method static Settings appAuthPageLayout(string $value = 'panel-right' | 'panel-center' | 'panel-right')
 * @method static Settings appCheckUpdatesInterval(int $value = 1)
 * @method static Settings appColorGrayMode(bool $value = true)
 * @method static Settings appColorWeakMode(bool $value = true)
 * @method static Settings appCompact(bool $value = true)
 * @method static Settings appContentCompact(string $value = "wide")
 * @method static Settings appDefaultAvatar(string $value)
 * @method static Settings appDynamicTitle(bool $value = true)
 * @method static Settings appEnableCheckUpdates(bool $value = true)
 * @method static Settings appEnablePreferences(bool $value = true)
 * @method static Settings appEnableRefreshToken(bool $value = true)
 * @method static Settings appLayout(string $value = "sidebar-mixed-nav")
 * @method static Settings appLocale(string $value = "zh-CN")
 * @method static Settings appLoginExpiredMode(string $value = "page")
 * @method static Settings appPreferencesButtonPosition(string $value = "auto")
 * @method static Settings appWatermark(bool $value = true)
 * @method static Settings breadcrumbEnable(bool $value = false)
 * @method static Settings breadcrumbHideOnlyOne(bool $value = false): static
 * @method static Settings breadcrumbShowHome(bool $value = false)
 * @method static Settings breadcrumbShowIcon(bool $value = false)
 * @method static Settings breadcrumbStyleType(string $value = 'background')
 * @method static Settings copyrightName(string $value)
 * @method static Settings copyrightLink(string $value)
 * @method static Settings copyrightDate(string $value)
 * @method static Settings copyrightEnable(bool $value = true)
 * @method static Settings copyrightIcp(string $value)
 * @method static Settings copyrightIcpLink(string $value)
 * @method static Settings copyrightSettingShow(bool $value = true)
 * @method static Settings footerEnable(bool $value = true)
 * @method static Settings footerFixed(bool $value = true)
 * @method static Settings headerEnable(bool $value = true)
 * @method static Settings headerHidden(bool $value = true)
 * @method static Settings headerMenuAlign(string $value = 'start')
 * @method static Settings headerMode(string $value = 'fixed')
 * @method static Settings logoEnable(bool $value = true)
 * @method static Settings logoSource(string $value = "")
 * @method static Settings navigationName(bool $value = true)
 * @method static Settings navigationSplit(bool $value = true)
 * @method static Settings navigationStyleType(string $value = 'rounded')
 * @method static Settings shortcutKeysEnable(bool $value = true)
 * @method static Settings shortcutKeysGlobalLockScreen(bool $value = true)
 * @method static Settings shortcutKeysGlobalLogout(bool $value = true)
 * @method static Settings shortcutKeysGlobalPreferences(bool $value = true)
 * @method static Settings shortcutKeysGlobalSearch(bool $value = true)
 * @method static Settings sidebarAutoActivateChild(bool $value = true)
 * @method static Settings sidebarCollapsed(bool $value = true)
 * @method static Settings sidebarCollapsedShowTitle(bool $value = true)
 * @method static Settings sidebarEnable(bool $value = true)
 * @method static Settings sidebarExpandOnHover(bool $value = true)
 * @method static Settings sidebarExtraCollapse(bool $value = true)
 * @method static Settings sidebarHidden(bool $value = true)
 * @method static Settings sidebarWidth(int $value = 200)
 * @method static Settings tabbarDraggable(bool $value = true)
 * @method static Settings tabbarEnable(bool $value = true)
 * @method static Settings tabbarHeight(int $value = 38)
 * @method static Settings tabbarKeepAlive(bool $value = true)
 * @method static Settings tabbarMaxCount(int $value = 0)
 * @method static Settings tabbarMiddleClickToClose(bool $value = true)
 * @method static Settings tabbarPersist(bool $value = true)
 * @method static Settings tabbarShowIcon(bool $value = true)
 * @method static Settings tabbarShowMaximize(bool $value = true)
 * @method static Settings tabbarShowMore(bool $value = true)
 * @method static Settings tabbarStyleType(string $value = 'chrome')
 * @method static Settings tabbarWheelable(bool $value = true)
 * @method static Settings themeBuiltinType(string $value = 'violet')
 * @method static Settings themeColorDestructive(string $value = 'hsl(348 100% 61%)')
 * @method static Settings themeColorPrimary(string $value = 'hsl(245 82% 67%)')
 * @method static Settings themeColorSuccess(string $value = 'hsl(144 57% 58%)')
 * @method static Settings themeColorWarning(string $value = 'hsl(42 84% 61%)')
 * @method static Settings themeMode(string $value = 'light')
 * @method static Settings themeRadius(string $value = '0.25')
 * @method static Settings themeSemiDarkHeader(bool $value = true)
 * @method static Settings themeSemiDarkSidebar(bool $value = true)
 * @method static Settings transitionName(string $value = 'fade-slide')
 * @method static Settings transitionEnable(bool $value = true)
 * @method static Settings transitionLoading(bool $value = true)
 * @method static Settings transitionProgress(bool $value = true)
 * @method static Settings widgetFullscreen(bool $value = true)
 * @method static Settings widgetGlobalSearch(bool $value = true)
 * @method static Settings widgetLanguageToggle(bool $value = true)
 * @method static Settings widgetLockScreen(bool $value = true)
 * @method static Settings widgetNotification(bool $value = true)
 * @method static Settings widgetRefresh(bool $value = true)
 * @method static Settings widgetSidebarToggle(bool $value = true)
 * @method static Settings widgetThemeToggle(bool $value = true)
 * @method Settings margeApp(string $key, mixed $value = null)
 * @method Settings margeBreadcrumb(string $key, mixed $value = null)
 * @method Settings margeCopyright(string $key, mixed $value = null)
 * @method Settings margeHeader(string $key, mixed $value = null)
 * @method Settings margeFooter(string $key, mixed $value = null)
 * @method Settings margeLogo(string $key, mixed $value = null)
 * @method Settings margeNavigation(string $key, mixed $value = null)
 * @method Settings margeShortcutKeys(string $key, mixed $value = null)
 * @method Settings margeSidebar(string $key, mixed $value = null)
 * @method Settings margeTabbar(string $key, mixed $value = null)
 * @method Settings margeTheme(string $key, mixed $value = null)
 * @method Settings margeTransition(string $key, mixed $value = null)
 * @method Settings margeWidget(string $key, mixed $value = null)
 * @method static Settings app(string $key, mixed $value = null)
 * @method static Settings breadcrumb(string $key, mixed $value = null)
 * @method static Settings copyright(string $key, mixed $value = null)
 * @method static Settings header(string $key, mixed $value = null)
 * @method static Settings footer(string $key, mixed $value = null)
 * @method static Settings logo(string $key, mixed $value = null)
 * @method static Settings navigation(string $key, mixed $value = null)
 * @method static Settings shortcutKeys(string $key, mixed $value = null)
 * @method static Settings sidebar(string $key, mixed $value = null)
 * @method static Settings tabbar(string $key, mixed $value = null)
 * @method static Settings theme(string $key, mixed $value = null)
 * @method static Settings transition(string $key, mixed $value = null)
 * @method static Settings widget(string $key, mixed $value = null)
 */
class Settings extends Fluent
{
    private static Settings $instance;

    private static array $allowAttrs = [
        "app","breadcrumb","copyright","header","footer","logo","navigation",
        "shortcutKeys","sidebar","tabbar","theme","transition","widget"
    ];

    protected array $attributes = [];

    public function __construct(){
       parent::__construct();
    }

    /**
     * @return Settings
     */
    public static function make(): Settings
    {
        if (!isset(self::$instance) || !(self::$instance instanceof self)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function setAttr(string $attribute,string $key, mixed $value = null): static
    {
        $app = $this->attributes[$attribute]??[];
        $app[$key] = $value;
        $this->attributes[$attribute] = $app;
        return $this;
    }


    /**
     * @param bool $enable
     * @param bool $fixed
     * @return $this
     */
    public function setFooter(bool $enable = true, bool $fixed = true): static
    {
        return $this->margeFooter("enable", $enable)->margeFooter("fixed", $fixed);
    }

    /**
     * @param bool $enable
     * @param string $source
     * @return $this
     */
    public function setLogo(bool $enable = true, string $source = ""): static
    {
        return $this->margeLogo("enable", $enable)->margeLogo("source", $source);
    }


    /**
     * @param bool $darkHeader
     * @param bool $darkSidebar
     * @return $this
     */
    public function setThemeSemiDark(bool $darkHeader = true, bool $darkSidebar = true): static
    {
        return $this->margeTheme("semiDarkHeader", $darkHeader)->margeTheme("semiDarkSidebar", $darkSidebar);
    }

    /**
     * @param string $name
     * @param bool $enable
     * @param bool $loading
     * @param bool $progress
     * @return $this
     */
    public function setTransition(string $name, bool $enable = true, bool $loading = true, bool $progress = true): static
    {
        $this->attributes["transition"] = [
          'name'=>$name,
          'enable'=>$enable,
          'loading'=>$loading,
          'progress'=>$progress,
        ];
        return $this;
    }

    public function buildMethod(string $method, array $parameters): static
    {
        if (str_starts_with($method,"marge")){
            $method = lcfirst(str_replace("marge","",$method));
            if (in_array($method,self::$allowAttrs)){
                return $this->setAttr($method,...$parameters);
            }
        }
        if (str_starts_with($method,"set")){
            $method = str_replace("set","",$method);
            if (str_contains($method,"ShortcutKeys")){
                $keyName = lcfirst(str_replace("ShortcutKeys","",$method));
                return $this->setAttr("shortcutKeys",lcfirst($keyName),...$parameters);
            }else{
                preg_match_all('/([A-Z][a-z]*)|([A-Z]+)/', $method, $matches);
                $words = $matches[0];
                if ($words){
                    $methodName = lcfirst($words[0]);
                    if (in_array($methodName, self::$allowAttrs)){
                        array_shift($words);
                        $keyName = implode("",$words);
                        return $this->setAttr($methodName, lcfirst($keyName),...$parameters);
                    }
                }
            }
        }
        throw new BadMethodCallException(sprintf(
            'Method %s::%s does not exist.', static::class, $method
        ));
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method
     * @param array $parameters
     * @return Settings
     *
     * @throws BadMethodCallException
     */
    public function __call(string $method, array $parameters)
    {
        return $this->buildMethod($method, $parameters);
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method
     * @param array $parameters
     * @return Settings
     *
     * @throws BadMethodCallException
     */
    public static function __callStatic(string $method, array $parameters)
    {
        $self = self::make();
        $methodName = "set".ucfirst($method);
        return $self->buildMethod($methodName, $parameters);
    }
}
